package com.acme.bankapp.domain.bank.client;

import com.acme.bankapp.domain.bank.account.Account;
import com.acme.bankapp.domain.bank.exception.AccountExistsException;

import java.io.Serializable;
import java.util.*;

/**
 * This class represents bank client
 *
 * @author Alexander Kotov
 */
public class Client implements Serializable {
    private final ClientInfo clientInfo;
    private Map<Integer, Account> accounts = new HashMap<>();

    public Client(String name, Gender gender) {
        this(name, gender, null);
    }

    public Client(String name, Gender gender, String emailAddress) {
        super();
        clientInfo = new ClientInfo(gender, name, emailAddress);
    }

    public Client(String name, Gender gender, String emailAddress, Account... accounts) throws AccountExistsException {
        this(name, gender, emailAddress);
        for (Account account : accounts) {
            addAccount(account);
        }
    }

    public String getName() {
        return clientInfo.getName();
    }

    public Gender getGender() {
        return clientInfo.getGender();
    }

    public String getEmailAddress() {
        return clientInfo.getEmailAddress();
    }

    /**
     * @return client's {@linkplain Account accounts}
     */
    public Collection<Account> getAccounts() {
        return Collections.unmodifiableCollection(accounts.values());
    }

    public Account getAccountById(int id) {
          return accounts.get(id);
    }

    /**
     * This method adds {@code account} to client
     *
     * @param account object to add
     */
    public void addAccount(Account account) throws AccountExistsException {
        if (account == null) {
            throw new IllegalArgumentException("Invalid account object");
        }
        int id = account.getId();
        if (accounts.containsKey(id)) {
           throw new AccountExistsException(id);
        }
        accounts.put(id, account);
    }

    @Override
    public String toString() {
        return clientInfo.toString();
    }

    public ClientInfo getClientInfo() {
        return clientInfo;
    }
}
